package com.example.downloader.upload;

import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class Uploader<R> {
    final TaskExecutor<R> mTaskExecutor;
    private TaskQueue<R> mTaskQueue = new TaskQueue<>();

    public Uploader(TaskExecutor<R> taskExecutor) {
        this.mTaskExecutor = taskExecutor;
    }

    public void load(String path, Callback<R> callback) {
//        mTaskQueue.releaseCallback(callback.getId());
        final Callback<R> attached = callback == null ? null : mTaskQueue.popTaskCallback(callback.getId());
        if (attached != null) {

            final Task<R> task = attached.getTask();
            if (task != null) {
//                Log.i("@@", "@@@@:" + path + "," + callback.getId());

                task.removeCallback(attached);
                attached.detachTask();
            }
        }

        final Task<R> task = mTaskQueue.getTask(path);
        if (task != null && task.isActive()) {
            if (callback != null) {
                callback.attachTask(task);
                task.callAndAddCallback(callback);
                mTaskQueue.addTaskCallback(callback);
            }
        } else {
            final Task<R> N = new Task<>(mTaskExecutor, mTaskQueue, path);
            if (callback != null) {
                N.addCallback(callback);
                callback.attachTask(N);
            }
            mTaskQueue.pushNewTask(N, callback);
            N.execute();
        }

    }

    public void cancel(String path) {
        final Task<R> task = mTaskQueue.getTask(path);
        if (task != null && task.isActive()) {
            task.cancel();
        }
    }

    public void cancelAll() {
        Set<Map.Entry<String, Task<R>>> set = mTaskQueue.getTasks().entrySet();
        Iterator<Map.Entry<String, Task<R>>> iterator = set.iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, Task<R>> entry = iterator.next();
            final Task<R> task = entry.getValue();
            if (task != null && task.isActive()) {
                task.cancel();
            }
        }
    }

}
